import multiprocessing
import os
import time

"""
多进程的设计:
    进程控制

    terminate(self):关闭进程
    is_alive(self):是否存活
    join(self,timeout):加入队列强制执行
    p.is_alive(): 判断子线程p1是否存活
    p.terminate(): 强制结束
    p.Process(daemon=true): 守护进程,主线程开启同时他也开启,主线程结束他也结束
    pid = os.fork() # 创建子进程 只支持linux  windows会报错:Has no attribute fork  
    {pid<0创建失败,pid=0子进程获取数据,pid>0父进程获取数据 }
    psutil :进程工具,pip install psutil 

    # join()
    所有的进程通过start()方法启动,而后多个进程进入到阻塞队列,这时候某一个进程是不可能强占cpu的
    如果这个时候有一个进程必须要现在执行,那就要使用join()
    
# 进程池
        多进程可以提高程序运行效率,但是传统的的多进程模式只适合并发并不多的情况:成百上千的并发进程就不适合使用了,
    会造成资源过多的消耗,导致资源不足的问题,从而降低了系统性能,所以要提高资源的利用率,以及进程的可复用性
    
    
# 管道
        为什么使用管道?
        进程和进程之间不能直接通讯,需要用管道连接两个进程才能通讯
        
# 进程队列(Queue)
    为什么使用对列?(使用场景)
    相当于是一个缓冲区,生产出来的数据,先存到队列(queue)中,然后消费进程从队列中(queue)取出数据
    从而实现进程的数据交互
    
# subprocess
    这个模块是干什么的?
    进行系统和Python的交互
        args,   # 命令
        bufsize=-1, # 缓冲区大小
        stdin=None, # 标准输入
        stdout=None, # 标准输出
        shell=False, # 是否是命令
        cwd=None, # 当前工作路径
        encoding=None, # 编码
        errors=None #编码
        
        # subprocess最强大的功能是
        可以使用标准输入,标准输出,和错误输出,进行进程的数据通信操作
        例子:
            使用脚本调用Python交互式的环境
            像进程执行读写操作
            
# Manger.list()  dict()
    为什么要要用manager.list()?
    实现这10 个进程的 [ 跨进程操作 ]!!!!
    并发执行,但是要求数据的一致性,就要进行进程控制,
    manger = multiprocessing.Manager()# 创建共享数据对象
    
# 并发执行会导致的问题?
    数据的一致性,无法保证
"""


# 卖票
def worker(dict):
    while 1:
        number = dict.get('ticket')
        if number >0:
            time.sleep(1)# 问题来了
            number-=1
            dict.update({'ticket':number})
            print('[{}]   余票数:[{}]'.format(multiprocessing.current_process().name, number))
        else:
            print('{} 已经没有票了....'.format(multiprocessing.current_process().name,))
            break


def main():
    manger = multiprocessing.Manager()# 创建共享数据对象
    manger_dict = manger.dict({"ticket":10})
    p_children = [multiprocessing.Process(target=worker,args=(manger_dict,),name='买票者:{}'.format(item)) for item in range(10)]
    for p_child in p_children:
        p_child.start()
    for p_child in p_children:
        p_child.join()

    print(manger_dict)
if __name__ == '__main__':
    main()